#include "simple/support/iterator/byte.hpp"

#include <cassert>
#include <array>
#include <algorithm>
#include <numeric>

using namespace simple::support;

void ProxySemantics()
{
	// using ici = std::tuple<int, char, int>; // not trivially copyable -_-
	struct ici {
		int i;
		char c;
		int i2;
		bool operator==(ici other) { return i == other.i && c == other.c && i2 == other.i2; }
		bool operator!=(ici other) { return not ((*this) == other); }
		void swap(ici& other) { std::swap(i, other.i); std::swap(c, other.c); std::swap(i2, other.i2); }
	};

	ici x{};
	byte_iterator<ici> b{reinterpret_cast<std::byte*>(&x)};
	*b = ici{1,2,3};
	assert((x == ici{1,2,3}));
	ici y{2,3,4};
	b->swap(y);
	assert((x == ici{2,3,4}));
	assert((y == ici{1,2,3}));

	byte_iterator<ici> bb{reinterpret_cast<std::byte*>(&y)};
	*b = *bb;
	assert((x == ici{1,2,3}));
	assert((y == x));
}

void BasicAlgos()
{
	std::array<std::byte, sizeof(int) * 13> arr{};
	byte_iterator<int> begin{arr.data()};
	byte_iterator<int> end{arr.data() + arr.size()};

	std::iota(begin, end, 1);
	std::array iota {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
	assert(( std::equal(begin, end, iota.begin(), iota.end()) ));

	std::transform(begin, end, begin, [](int x) { return x * 5; });
	std::array fivota {5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65};
	assert(( std::equal(begin, end, fivota.begin(), fivota.end()) ));
}

int main()
{
	ProxySemantics();
	BasicAlgos();
	return 0;
}
